home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
shellasm.arc
/
SHELL.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-03-03
|
7KB
|
356 lines
name shell
page 55,132
title 'Shell.asm -- simple MS-DOS shell'
;############################################################################
;
; 03-03-88 This code is based on the work of Ray Duncan in his
; book 'Advanced MS-DOS'- "The Microsoft guide for Assembly
; Language and C programmers." published by Microsoft Press -
; (C)1986 by Ray Duncan. The program SHELL.ASM is shown
; on pages 199 - 205.
;
; The code here is optimized for maximum speed of response and
; the missing END statement has been added.
;
; Mr. Duncan also presents a C version of this program
; on pages 195 - 198 along with an excellent discussion
; and explanation of the MS-DOS EXEC function.
;
; This code and/or the C version is an excellent start for
; building your own command interpreter. Items not recognized
; by SHELL are passed to the MS-DOS COMMAND.COM for internal
; or external processing.
;
; As presented here a very minimal amount of memory is used
; by the program. The C version would of course have a bigger
; .EXE file and probably be slower.
;
; L. B. Neal
; Sunnyvale, CA
; March 3, 1988
; PYSMATIC BBS 408-992-0372
;#############################################################################
STDIN EQU 0
STDOUT EQU 1
STDERR EQU 2
CR EQU 0DH
LF EQU 0AH
BLANK EQU 20H
ESC_S EQU 01BH
;--------------------------------------------
;
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:DATA,SS:STACK
SHELL PROC FAR
MOV AX,DATA
MOV DS,AX
MOV AX,ES:[002CH]
MOV ENV_SEG,AX
MOV BX,100H
MOV AH,04AH
INT 21H
JNC SHELL1
MOV DX,OFFSET MSG1
MOV CX,MSG1_LENGTH
JMP SHELL4
SHELL1: CALL GET_COMSPEC ; Get the COMSPEC
JNC SHELL2
MOV DX,OFFSET MSG3
MOV CX,MSG3_LENGTH
JMP SHELL4
SHELL2: MOV DX,OFFSET SHELL3 ; Set CNTR-C vector
MOV AX,CS
MOV DS,AX
MOV AX,2523H
INT 21H
MOV AX,DATA
MOV DS,AX
MOV ES,AX
;-------------------------------------------------------------
; This is the main wait for input processing loop in the SHELL mode.
;
SHELL3: MOV DX,OFFSET PROMPT ; Get_cmd inline coded
MOV CX,PROMPT_LENGTH
MOV BX,STDOUT ; Write prompt to screen
MOV AH,40H
INT 21H
MOV DX,OFFSET INP_BUF
MOV CX,INP_BUF_LENGTH
MOV BX,STDIN ; Read the keyboard
MOV AH,3FH
INT 21H
MOV SI,OFFSET INP_BUF
MOV CX,INP_BUF_LENGTH
CMP BYTE PTR [SI],0DH ; Skip rest if CR
JNE GCMD1 ; This gives much faster response
JMP SHORT SHELL1
;------------------------------------------------------------------------
; Here the command line is processed if was not just a CR
;
GCMD1: CMP BYTE PTR [SI],'a'
JAE CK_ALF
JMP SHORT GCMD2
CK_ALF: CMP BYTE PTR [SI],'z'
JBE UPCASE
JMP GCMD2
UPCASE: SUB BYTE PTR [SI],'a'-'A'
GCMD2: INC SI
LOOP GCMD1
MOV SI,OFFSET COMMANDS
INTR1: CMP BYTE PTR [SI],0
JE INTR7
MOV DI,OFFSET INP_BUF
INTR2: CMP BYTE PTR [DI],BLANK
JNE INTR3
INC DI
JMP INTR2
INTR3: MOV AL,[SI]
OR AL,AL
JZ INTR4
CMP AL,[DI]
JNZ INTR6
INC SI
INC DI
JMP INTR3
INTR4: CMP BYTE PTR [DI],CR
JE INTR5
CMP BYTE PTR [DI],BLANK
JNE INTR6
INTR5: CALL WORD PTR [SI+1]
CLC
JMP READ ; Read CMD line again
INTR6: LODSB
OR AL,AL
JNZ INTR6
ADD SI,2
JMP INTR1
INTR7: STC
READ: JNC SHELL3 ; Loop on cmd line again
CALL EXTRINSIC ; Send external command to Comamnd.com
JMP SHELL3
SHELL4: MOV BX,STDERR
MOV AH,40H
INT 21H
MOV AX,4C01H
INT 21H
SHELL ENDP
STK_SEG DW 0
STK_PTR DW 0
;----------------------------------------------------
; Here we pass the command line to COMMAND.COM when
; SHELL.EXE can't handle the string.
;
EXTRINSIC PROC NEAR
MOV AL,CR
MOV CX,CMD_TAIL_LENGTH
MOV DI,OFFSET CMD_TAIL+1
CLD
REPNZ SCASB
MOV AX,DI
SUB AX,OFFSET CMD_TAIL+2
MOV CMD_TAIL,AL
MOV PAR_CMD,OFFSET CMD_TAIL
CALL EXEC
RET
EXTRINSIC ENDP
;------------------------------------------------------
; This proceedure gets the comspec
;
GET_COMSPEC PROC NEAR
MOV SI,OFFSET COM_VAR
CALL GET_ENV
JC GCSP2
MOV SI,OFFSET COM_SPEC
GCSP1: MOV AL,ES:[DI]
MOV [SI],AL
INC SI
INC DI
OR AL,AL
JNZ GCSP1
GCSP2: RET
GET_COMSPEC ENDP
;-----------------------------------------------
; Get the environment information
;
GET_ENV PROC NEAR
MOV ES,ENV_SEG
XOR DI,DI
GENV1: MOV BX,SI
CMP BYTE PTR ES:[DI],0
JNE GENV2
STC
RET
GENV2: MOV AL,[BX]
OR AL,AL
JZ GENV3
CMP AL,ES:[DI]
JNE GENV4
INC BX
INC DI
JMP GENV2
GENV3: RET
GENV4: XOR AL,AL
MOV CX,-1
CLD
REPNZ SCASB
JMP GENV1
GET_ENV ENDP
;--------------------------------------------------
; Here we call MS-DOS EXEC function to run COMMAND.COM.
;
EXEC PROC NEAR
PUSH DS
PUSH ES
MOV CS:STK_SEG,SS
MOV CS:STK_PTR,SP
MOV DX,OFFSET COM_SPEC
MOV BX,OFFSET PAR_BLK
MOV AH,04BH
MOV AL,0
INT 21H
MOV SS,CS:STK_SEG
MOV SP,CS:STK_PTR
POP ES
POP DS
JNC EXEC1
MOV DX,OFFSET MSG2
MOV CX,MSG2_LENGTH
MOV BX,STDERR
MOV AH,040H
INT 21H
EXEC1: RET
EXEC ENDP
;---------------------------------------------------------
; A simple ANSI.SYS internal command to clear the screen.
;
CLS_CMD PROC NEAR
MOV DX,OFFSET CLS_STR
MOV CX,CLS_STR_LENGTH
MOV BX,STDOUT
MOV AH,040H
INT 21H
RET
CLS_CMD ENDP
;---------------------------------------------------------
; Internal command to run COMMAND.COM
;
DOS_CMD PROC NEAR
MOV PAR_CMD,OFFSET NULTAIL
CALL EXEC
RET
DOS_CMD ENDP
;--------------------------------------------------------
; Internal command to leave SHELL.EXE.
;
EXIT_CMD PROC NEAR
MOV AX,04C00H
INT 21H
EXIT_CMD ENDP
CSEG ENDS
;--------------------------------------------
STACK SEGMENT PARA STACK 'STACK'
DW 64 DUP(?)
STACK ENDS
;---------------------------------------------
DATA SEGMENT PARA PUBLIC 'DATA'
COMMANDS EQU $ ; The sample command table for
DB 'CLS',0 ; this command interpreter
DW CLS_CMD
DB 'DOS',0
DW DOS_CMD
DB 'EXIT',0
DW EXIT_CMD
DB 0
COM_VAR DB 'COMSPEC=',0
COM_SPEC DB 80 DUP(0)
NULTAIL DB 0,CR
CMD_TAIL DB 0,' /C '
INP_BUF DB 80 DUP(0)
INP_BUF_LENGTH EQU $-INP_BUF
CMD_TAIL_LENGTH EQU $-CMD_TAIL-1
;-----------------------------------------------------------
; The definition of SHELL.EXE's prompt.
;
PROMPT DB CR,'SHELL:> '
PROMPT_LENGTH EQU $-PROMPT
ENV_SEG DW 0
;-----------------------------------------------------------
; Internal messages for SHELL.EXE errors
;
MSG1 DB CR,LF
DB 'Unable to de-allocate memory.'
DB CR,LF
MSG1_LENGTH EQU $-MSG1
MSG2 DB CR,LF
DB 'EXEC of COMMAND.COM failed.'
DB CR,LF
MSG2_LENGTH EQU $-MSG2
MSG3 DB CR,LF
DB 'No COMSPEC variable in Environment.'
DB CR,LF
MSG3_LENGTH EQU $-MSG3
CLS_STR DB ESC_S,'[2J' ; ANSI.SYS clear screen string.
CLS_STR_LENGTH EQU $-CLS_STR
PAR_BLK EQU $
DW 0
PAR_CMD DW OFFSET CMD_TAIL
DW SEG CMD_TAIL
DD -1
DD -1
DATA ENDS
END SHELL
END